/*
 * iPersonaBUS.cpp
 *
 *  Created on: 05/07/2014
 *      Author: migue
 */

#include "iPersonaBUS.h"
#include "../comun/ServidorIDs.h"
#include "../comun/ServidorRemoto.h"

#include <syslog.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/wait.h>


iPersonaBUS::iPersonaBUS(int numBus) :
_cEnvio(RUTA, COLASISTEMA), _cRecibo(RUTA, COLARECIBO_CLI)
{
	//ServidorIDs serv;
	//_mtypeBUS = serv.idBUS(numBUS);

	ServidorRemoto serv;


	_numBUS = numBus;
	_mtypeBUS = serv.pedirIdBus(_numBUS);
	_idBroker = serv.idBrokerConectado();


	_idsConsultados = false;

	lanzarCorteDeColas();
}


iPersonaBUS::~iPersonaBUS() {
	MENSAJE msj;
	msj.destinatario = _mtypeBUS;
	msj.destinatarioFinal = _idBroker;
	msj.origen = _mtypeBUS;

	msj.tipo = Tipos::MSJ_IPC;
	msj._ipc.op_ipc = TIPO_FINALIZAR;

	_cEnvio.enviar(&msj, TAM_MENSAJE);

	usleep(1000);

	waitpid(-1, 0, WNOHANG);
	waitpid(-1, 0, WNOHANG);
}

void iPersonaBUS::lanzarCorteDeColas() {
	char arg[20];
	int pid;

	sprintf(arg, "%i", _mtypeBUS);

	pid = fork();
	if (pid == 0) {
		execl("./conexBrokerCliente", "conexBrokerCliente", arg, "E", NULL);
		syslog(LOG_ERR, "Error al lanzar proceso de conexion con Broker, BUS: %i ", _numBUS);
		exit(EXIT_FAILURE);
	}

	pid = fork();
	if (pid == 0) {
		execl("./conexBrokerCliente", "conexBrokerCliente", arg, "R", NULL);
		syslog(LOG_ERR, "Error al lanzar proceso de conexion con Broker, BUS: %i ", _numBUS);
		exit(EXIT_FAILURE);
	}
}


int iPersonaBUS::elegirSala(Tipos::LugarDeSala lugar) {
	consultarIds();
	if (lugar == Tipos::LUGAR_ENTRADA)
		return _idSalaEntrada;
	else
		return _idSalaZoo;
}

int iPersonaBUS::subirPersona(int numSala, Tipos::LugarDeSala lugar) {
	MENSAJE msj;
	int mtypeSala;
	ServidorIDs serv;

	//Tipos::LugarDeSala lugarSala = lugar;

	//mtypeSala = serv.idSala(numSala, Tipos::TP_SALIDA, lugarSala);
	mtypeSala = elegirSala(lugar);


//	msj.destinatario = mtypeSala;
//	msj.origen = _mtypeBUS;
//	msj.id = 0;

	msj.destinatario = _mtypeBUS;
	msj.origen = _mtypeBUS;
	msj.destinatarioFinal = mtypeSala;
	msj.id = 0;

	msj.tipo = Tipos::MSJ_SUBIR_PERSONA_A_BUS;


	// Mensaje de PERMITIR_ASCENSO
	//_cola.enviar((void*) &msj, TAM_MENSAJE);
	_cEnvio.enviar((void*) &msj, TAM_MENSAJE);

	syslog(LOG_INFO, "Mensaje enviado a Sala(N°%i,id-%i) para subirPersona desde BUS(N°%i,id-%i)", numSala,mtypeSala, _numBUS,_mtypeBUS);

	//_cola.recibir((void*) &msj, TAM_MENSAJE, _mtypeBUS);
	//_cRecibo.recibir((void*) &msj, TAM_MENSAJE, _mtypeBUS);
	_cRecibo.recibirMensaje(msj, Tipos::MSJ_CONFIRMAR_SUBIDA_A_BUS , _mtypeBUS);


	if (msj.tipo != Tipos::MSJ_CONFIRMAR_SUBIDA_A_BUS) {
		syslog(LOG_ERR, "TIPO INCORRECTO esperado: %i, llego: %i. Recibido por BUS(N°%i,id-%i) de id-%li",
				(int) Tipos::MSJ_CONFIRMAR_SUBIDA_A_BUS, (int) msj.tipo, _numBUS,_mtypeBUS, msj.origen);
	}
	else {
		syslog(LOG_INFO, "Mensaje recibido por BUS(N°%i,id-%i) de id-%li", _numBUS,_mtypeBUS, msj.origen);
	}

	// Retorno ID de Persona
	return msj.id;
}

void iPersonaBUS::descenderPersona(int idPersona) {
	MENSAJE msj;

//	msj.destinatario = idPersona;
//	msj.origen = _mtypeBUS;
//	msj.id = 0;

	msj.destinatario = _mtypeBUS;
	msj.origen = _mtypeBUS;
	msj.destinatarioFinal = idPersona;
	msj.id = 0;


	msj.tipo = Tipos::MSJ_BAJAR_DE_BUS;

	// Mensaje de PERMITIR_ASCENSO
	//_cola.enviar((void*) &msj, TAM_MENSAJE);
	_cEnvio.enviar((void*) &msj, TAM_MENSAJE);
	syslog(LOG_INFO, "Mensaje enviado a Persona(id-%i) para descenderPersona desde BUS(N°%i,id-%i)",idPersona, _numBUS,_mtypeBUS);

	//_cola.recibir((void*) &msj, TAM_MENSAJE, _mtypeBUS);
	//_cRecibo.recibir((void*) &msj, TAM_MENSAJE, _mtypeBUS);
	_cRecibo.recibirMensaje(msj, Tipos::MSJ_CONFIMAR_BAJADA_DE_BUS, _mtypeBUS);

	if (msj.tipo != Tipos::MSJ_CONFIMAR_BAJADA_DE_BUS) {
		syslog(LOG_ERR, "TIPO INCORRECTO(esperado: %i llego: %i) por BUS(N°%i,id-%i) para confirmar descendo de Persona(id-%li)",
				(int)Tipos::MSJ_CONFIMAR_BAJADA_DE_BUS ,(int)msj.tipo, _numBUS,_mtypeBUS, msj.origen);
	}
	else {
		syslog(LOG_INFO, "Mensaje recbido por BUS(N°%i,id-%i) para confirmar descendo de Persona(id-%li)", _numBUS,_mtypeBUS, msj.origen);
	}

}

int iPersonaBUS::idBus() {
	return _mtypeBUS;
}

int iPersonaBUS::idBroker() {
	return _idBroker;
}

void iPersonaBUS::consultarIds() {

	if (_idsConsultados == false) {
		_idsConsultados = true;
		ServidorRemoto serv;
		_idSalaEntrada = serv.consultarIdSala(_numBUS, Tipos::TP_SALIDA, Tipos::LUGAR_ENTRADA);
		_idSalaZoo = serv.consultarIdSala(_numBUS, Tipos::TP_SALIDA, Tipos::LUGAR_ZOO);

	}
}
